/**
 * 
 */
package wangjg.commons.bean;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

/**
 * sun jvm
 * @author wangjg
 *
 */
@SuppressWarnings("rawtypes")
public class ReflectionUtil {
	
	public static Class getPropertyType(Object bean, String property) {
		try {
			PropertyDescriptor pd = new PropertyDescriptor(property, bean.getClass());
			return pd.getPropertyType();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static Object getPropertyValue(Object bean, String property){
		try {
			PropertyDescriptor pd = getPropertyDescriptor(property, bean.getClass());
			Method method = pd.getReadMethod();
			return method.invoke(bean);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static void setPropertyValue(Object bean, String property, Object value){
		try {
			PropertyDescriptor pd = getPropertyDescriptor(property, bean.getClass());
			Method method = pd.getWriteMethod();
			method.invoke(bean, value);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 遍历
	 * @param propertyClazz 遍历哪一个类的属性
	 * @param valueBean		获取哪一个对象的属性值
	 * @param ignoreReadOnly 忽略只读属性
	 * @param handle		处理器
	 * @throws Exception	异常
	 */
	public static void traverseProperties(Class propertyClazz, Object valueBean, boolean ignoreReadOnly, Callback handle){
		PropertyDescriptor[] pds = getPropertyDescriptor(propertyClazz);
        for(PropertyDescriptor prop:pds){
        	Method writeMethod = prop.getWriteMethod();
        	if(ignoreReadOnly && writeMethod==null){
        		continue;
        	}
        	Method readMethod = prop.getReadMethod();
        	Object pv = null;
			try {
				if(readMethod!=null && valueBean!=null){
					pv = readMethod.invoke(valueBean, Empty.ARRAY);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
        	handle.handle(propertyClazz, writeMethod, readMethod, prop.getName(), pv);
        }
	}
	
	public static void traverseProperties(Class clazz, Object[] beanArray, boolean ignoreReadOnly, Callback handle){
	    PropertyDescriptor[] pds = getPropertyDescriptor(clazz);
	    for(PropertyDescriptor prop:pds){
	    	Method writeMethod = prop.getWriteMethod();
	    	if(ignoreReadOnly && writeMethod==null){
	    		continue;
	    	}
	    	Method readMethod = prop.getReadMethod();
	    	Object[] pvArray = new Object[beanArray.length];
	    	for(int i=0;i<beanArray.length;i++){
	    		Object bean = beanArray[i];
	        	Object pv = null;
				try {
					if(readMethod!=null && bean!=null){
						pv = readMethod.invoke(bean, Empty.ARRAY);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				pvArray[i] = pv;
	    	}
	    	handle.handle(clazz, writeMethod, readMethod, prop.getName(), pvArray);
	    }
	}
	
	private static PropertyDescriptor getPropertyDescriptor(String property, Class clazz){
		try {
			PropertyDescriptor pd = new PropertyDescriptor(property, clazz);
			return pd;
		} catch (IntrospectionException e) {
			throw new RuntimeException(e);
		}
	}

	private static PropertyDescriptor[] getPropertyDescriptor(Class clazz){
		BeanInfo beanInfo;
		try {
			beanInfo = Introspector.getBeanInfo(clazz);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
        
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
        return pds;
	}
	
	public static interface Callback{
		void handle(Class clazz, Method writeMethod, Method readMethod, String property, Object pv);
	}
	
	public static void main(String[] args) {

	}

}
